﻿using Aliyun.OSS;
using Aliyun.OSS.Common;
using Micro.Common.Core;
using System.Net;
using System.Text.RegularExpressions;

namespace Micro.AliyunOSS
{
    /// <summary>
    ///   "ALIYUN_OSS": {
    ///   "REGIONID": "oss-cn-hangzhou-internal.aliyuncs.com", //eg：cn-hangzhou
    ///   "KEY": "LTAIJhJIONQUvWjv",
    ///   "SECRET": "3k9sbwjkGZ5pdVOOaNZvI2c9yBt1SR",
    ///   "bucketName": "bucketName",
    ///   "domainUrl": "", //访问资源域名
    ///   "maxSize": 100 //上传文件大小限制 100M
    ///   }
    /// </summary>
    public sealed partial class OssHelper
    {
        private static string accessKey = AppSettings.GetConfig("ALIYUN_OSS:KEY");
        private static string accessSecret = AppSettings.GetConfig("ALIYUN_OSS:SECRET");
        private static string defaultRegionId = AppSettings.GetConfig("ALIYUN_OSS:REGIONID");
        private static string defaultBucketName = AppSettings.GetConfig("ALIYUN_OSS:bucketName");

        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="filestreams">文件流：</param>
        /// <param name="dirPath">存储路径： upload/2020/01/01/xxx.png</param>
        /// <param name="bucketName">存储桶：如果为空默认取配置文件</param>
        public static HttpStatusCode UploadFile(Stream filestreams, string dirPath, string bucketName = "")
        {
            if (string.IsNullOrEmpty(bucketName)) { bucketName = defaultBucketName; }
            var client = new OssClient(defaultRegionId, accessKey, accessSecret);
            try
            {
                dirPath = dirPath.Replace("\\", "/");
                var uploadResult = client.PutObject(bucketName, dirPath, filestreams);
                return uploadResult.HttpStatusCode;
            }
            catch (OssException ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            return HttpStatusCode.BadRequest;
        }

        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="bucketName"></param>
        /// <param name="bucketKey"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static bool UploadFile(string bucketName, string bucketKey, string filePath)
        {
            if (string.IsNullOrEmpty(bucketName)) { bucketName = defaultBucketName; }
            try
            {
                var client = new OssClient(defaultRegionId, accessKey, accessSecret);
                var putObjectResult = client.PutObject(bucketName, bucketKey, filePath);
                return putObjectResult?.HttpStatusCode == HttpStatusCode.OK;
            }
            catch (OssException ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            return default;
        }

        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="bucketName"></param>
        /// <param name="bucketKey"></param>
        /// <param name="stream"></param>
        public static bool UploadFile(string bucketName, string bucketKey, Stream stream)
        {
            if (string.IsNullOrEmpty(bucketName)) { bucketName = defaultBucketName; }
            var client = new OssClient(defaultRegionId, accessKey, accessSecret);
            try
            {
                var uploadResult = client.PutObject(bucketName, bucketKey, stream);
                return uploadResult?.HttpStatusCode == HttpStatusCode.OK;
            }
            catch (OssException ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            return default;
        }

        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="bucketKey"></param>
        /// <param name="dirPath"></param>
        /// <returns>https://blog.csdn.net/pk142536/article/details/99695234</returns>
        /// <param name="process">http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg?x-oss-process=image/resize,m_lfit,h_100,w_100</param>
        /// <returns></returns>
        public static Stream DownloadFile(string bucketKey, string dirPath, string process = "")
        {
            if (string.IsNullOrEmpty(bucketKey) || string.IsNullOrEmpty(dirPath)) return Stream.Null;
            try
            {
                OssClient client = new(defaultRegionId, accessKey, accessSecret);
                OssObject ossObject;
                if (string.IsNullOrEmpty(process))
                    ossObject = client.GetObject(bucketKey, dirPath);
                else
                    ossObject = client.GetObject(new GetObjectRequest(bucketKey, dirPath, process));
                return ossObject.Content;
            }
            catch (OssException ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            return Stream.Null;
        }

        /// <summary>
        /// 下载byte字节
        /// </summary>
        /// <param name="bucketKey"></param>
        /// <param name="dirPath"></param>
        /// <returns></returns>
        public static byte[] DownloadBytes(string bucketKey, string dirPath, string process = "")
        {
            var bytes = new byte[0];
            if (string.IsNullOrEmpty(bucketKey) || string.IsNullOrEmpty(dirPath)) return bytes;
            try
            {
                var client = new OssClient(defaultRegionId, accessKey, accessSecret);
                OssObject ossObject;
                if (string.IsNullOrEmpty(process))
                    ossObject = client.GetObject(bucketKey, dirPath);
                else
                    ossObject = client.GetObject(new GetObjectRequest(bucketKey, dirPath, process));
                using (var ms = new MemoryStream())
                {
                    ossObject.Content.CopyToAsync(ms).Wait(1000 * 5);
                    bytes = ms.ToArray();
                }
            }
            catch (OssException ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            return bytes;
        }

        /// <summary>
        /// 获取图片url
        /// </summary>
        /// <param name="bucketName"></param>
        /// <param name="key"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        public static string GetImageUri(string bucketName, string key, double width, double height)
        {
            if (string.IsNullOrEmpty(bucketName)) { bucketName = defaultBucketName; }
            try
            {
                var process = $"image/resize,m_fixed,w_{width},h_{height}";
                var req = new GeneratePresignedUriRequest(bucketName, key, SignHttpMethod.Get)
                {
                    Expiration = DateTime.Now.AddHours(1),
                    Process = process
                };
                var client = new OssClient(defaultRegionId, accessKey, accessSecret);
                var uri = client.GeneratePresignedUri(req);
                return Regex.Unescape(uri.ToString());
            }
            catch (OssException ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            return string.Empty;
        }

        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="dirPath"></param>
        /// <param name="bucketName"></param>
        /// <returns></returns>
        public static HttpStatusCode DeleteFile(string bucketName, string bucketKey)
        {
            if (string.IsNullOrEmpty(bucketName)) return HttpStatusCode.BadRequest;
            try
            {
                var client = new OssClient(defaultRegionId, accessKey, accessSecret);
                var deleteResult = client.DeleteObject(bucketName, bucketKey);
            }
            catch (OssException ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            return HttpStatusCode.BadRequest;
        }

        /// <summary>
        /// 批量删除指定前缀的所有文件
        /// </summary>
        /// <param name="bucketName"></param>
        /// <param name="prefix"></param>
        public static void DeleteFileByPrefix(string bucketName, string prefix)
        {
            if (string.IsNullOrEmpty(bucketName)) return;
            try
            {
                var client = new OssClient(defaultRegionId, accessKey, accessSecret);
                ObjectListing listResult;
                while ((listResult = client.ListObjects(bucketName, prefix)).ObjectSummaries.Any())
                {
                    var request = new DeleteObjectsRequest(bucketName, listResult.ObjectSummaries.Select(o => o.Key).ToList(), true);
                    client.DeleteObjects(request);
                }
            }
            catch (OssException ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
        }

        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="bucketName"></param>
        /// <param name="bucketKey"></param>
        /// <returns></returns>
        public static bool DeleteFileByBucketName(string bucketName, string bucketKey)
        {
            if (string.IsNullOrEmpty(bucketName)) return default;
            try
            {
                var client = new OssClient(defaultRegionId, accessKey, accessSecret);

                var deleteObjectResult = client.DeleteObject(bucketName, bucketKey);
                if (deleteObjectResult is null) return false;
                return !deleteObjectResult.DeleteMarker;
            }
            catch (OssException ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            return default;
        }

        /// <summary>
        /// 判断BucketName是否存在
        /// </summary>
        /// <param name="bucketName"></param>
        /// <returns></returns>
        public static bool DoesBucketExist(string bucketName)
        {
            if (string.IsNullOrWhiteSpace(bucketName))
                return false;

            var client = new OssClient(defaultRegionId, accessKey, accessSecret);
            return client.DoesBucketExist(bucketName);
        }

        /// <summary>
        /// 判断存储对象是否存在
        /// </summary>
        /// <param name="bucketName"></param>
        /// <param name="bucketKey"></param>
        /// <returns></returns>
        public static bool DoesObjectExist(string bucketName, string bucketKey)
        {
            if (string.IsNullOrWhiteSpace(bucketName) || string.IsNullOrWhiteSpace(bucketKey))
                return false;

            var client = new OssClient(defaultRegionId, accessKey, accessSecret);
            return client.DoesObjectExist(bucketName, bucketKey);
        }

        /// <summary>
        /// Stream转byte[]字节集合
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static byte[] StreamToBytes(Stream stream)
        {
            var bytes = new byte[0];
            if (stream is null || stream == Stream.Null) return bytes;
            try
            {
                using (var ms = new MemoryStream())
                {
                    stream.CopyToAsync(ms).Wait(1000 * 30);
                    bytes = ms.ToArray();
                }
            }
            catch (OssException ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"异常信息:{ex.Message}");
            }
            return bytes;
        }
    }
}